package orders

import (
	"context"
	"errors"
	"github.com/google/uuid"
	"github.com/kuangshp/go-utils/k"
	"github.com/shopspring/decimal"
	"gorm.io/gorm"
	"insighttracking/apps/customer/auth"
	"insighttracking/common/error"
	"insighttracking/common/utils"
	"insighttracking/query/bo"
	"insighttracking/query/dao"
	"insighttracking/query/model"
	"insighttracking/query/service"
	"net/http"

	"insighttracking/apps/customer/internal/svc"
	"insighttracking/apps/customer/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
	"os"
)

type CreateOrderApiLogic struct {
	logx.Logger
	ctx     context.Context
	svcCtx  *svc.ServiceContext
	Request *http.Request
}

func NewCreateOrderApiLogic(ctx context.Context, svcCtx *svc.ServiceContext, request *http.Request) *CreateOrderApiLogic {
	hostname, _ := os.Hostname()
	return &CreateOrderApiLogic{
		Logger: logx.WithContext(ctx).WithCallerSkip(0).WithFields(
			logx.Field("Log_UUID", uuid.New().String()),
			logx.Field("hostname", hostname)),
		ctx:     ctx,
		svcCtx:  svcCtx,
		Request: request,
	}
}

func (l *CreateOrderApiLogic) CreateOrderApi(req *types.OrdersReq) (resp *types.CreateOrdersResp, err error) {
	resp = &types.CreateOrdersResp{}
	accountInfo, err := auth.GetAccountInfo(l.svcCtx, l.Request)
	if err != nil {
		return
	}
	if req.OrdersDetailList == nil || len(req.OrdersDetailList) == 0 {
		return resp, errors.New("请传递商品信息")
	}
	var totalCount = decimal.NewFromInt(int64(len(req.OrdersDetailList)))
	spuIdList := k.Map(req.OrdersDetailList, func(item types.OrdersDetailReq, index int) int64 {
		return item.SpuID
	})
	spuEntities, err := service.SpuService.GetSpuDetailByIdListApi(l.ctx, spuIdList)
	if err != nil {
		return resp, errors.New("传递的商品id错误")
	}
	offSaleSpu := make([]int64, 0)
	for _, item := range spuEntities {
		if item.Status == 2 {
			offSaleSpu = append(offSaleSpu, item.ID)
		}
	}
	if len(offSaleSpu) > 0 {
		resp = &types.CreateOrdersResp{
			OffSaleSpu: offSaleSpu,
		}
		return resp, myerror.HasOffShelf
	}

	dishIdList := k.Map(req.OrdersDetailList, func(item types.OrdersDetailReq, index int) int64 {
		return item.DishesID
	})
	dishMap, err := service.DishService.GetDishInfoMapApi(l.ctx, dishIdList)
	if err != nil {
		return resp, errors.New("传递的商品id错误")
	}
	offSaleDish := make([]int64, 0)
	for _, item := range dishMap {
		if item.IsEnable != 1 {
			offSaleDish = append(offSaleDish, item.ID)
		}
	}
	if len(offSaleDish) > 0 {
		resp = &types.CreateOrdersResp{
			OffSaleDish: offSaleDish,
		}
		return resp, myerror.HasOffShelf
	}
	spuMap := k.ToMap(spuEntities, func(item *bo.SpuBo) (int64, *bo.SpuBo) {
		return item.ID, item
	})

	var totalAmount = decimal.Zero
	for _, item := range req.OrdersDetailList {
		price, _ := decimal.NewFromString(item.SnapshotPrice)
		spuCount, _ := decimal.NewFromString(item.SpuCount)
		// 计算总金额
		totalAmount = totalAmount.Add(spuCount.Mul(price))
	}
	// 获取企业默认仓库
	warehouseEntity, err := service.WarehouseService.GetWarehouseByEnterpriseDefaultIdApi(l.ctx, accountInfo.EnterpriseId)
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return resp, errors.New("请先设置默认仓库")
	}
	tx := dao.Use(l.svcCtx.MysqlDb).Begin()

	// 订单数据
	ordersData := model.OrdersEntity{
		OrderNo:            utils.GenerateTodayOrderNo(l.svcCtx.RedisDb, "DD"), // 订单流水号
		EnterpriseID:       accountInfo.EnterpriseId,                           // 关联到enterprise表主键id
		CustomerID:         accountInfo.CustomerId,                             // 客户id,关联到enterprise_customer表主键id
		Remark:             req.Remark,                                         // 订单备注
		TotalAmount:        totalAmount,                                        // 订单金额
		TotalCount:         totalCount,                                         // 订单商品数量
		SendGoodsDate:      utils.DateTimeStrToTime(req.SendGoodsDate),         // 发货日期
		SettlementMethod:   req.SettlementMethod,                               // 结算方式
		SendGoodsMethod:    req.SendGoodsMethod,                                // 配送方式
		Status:             0,                                                  // 订单状态,0表示已下单(待采购),1表示采购中,2表示已采购,3待入库，4已入库，5已发货,6已收货
		ReceiveGoodsName:   req.ReceiveGoodsName,                               // 收货员姓名
		ReceiveGoodsMobile: req.ReceiveGoodsMobile,                             // 收货人手机号码
		ReceiveAddress:     req.ReceiveAddress,                                 // 收货人地址
		WarehouseID:        warehouseEntity.ID,                                 // 默认仓库
	}
	if err1 := tx.OrdersEntity.WithContext(l.ctx).Omit(dao.OrdersEntity.PurchaserID).Create(&ordersData); err1 != nil {
		if err = tx.Rollback(); err != nil {
			return
		}
		return resp, errors.New("创建订单主数据失败")
	}

	// 订单详情
	var orderDetailList = make([]*model.OrdersDetailEntity, 0)
	for _, item := range req.OrdersDetailList {
		spu, isOk := spuMap[item.SpuID]
		dish, isOk2 := dishMap[item.DishesID]
		if !isOk && !isOk2 {
			continue
		}
		price, _ := decimal.NewFromString(item.SnapshotPrice)
		spuCount, _ := decimal.NewFromString(item.SpuCount)
		var snapshotName, snapshotProductImageURL, snapshotCategory, snapshotUnit, snapshotBrand, snapshotSupplier string
		var snapshotCategoryID, snapshotSpuType int64
		if item.SpuID != 0 {
			snapshotName = k.If(spu != nil, spu.Name, "")
			snapshotProductImageURL = k.If(spu != nil, spu.ProductImageURL, "")
			snapshotCategory = k.If(spu != nil, spu.CategoryName, "")
			snapshotCategoryID = k.If(spu != nil, spu.CategoryId, 0)
			snapshotUnit = k.If(spu != nil, spu.UnitName, "")
			snapshotBrand = k.If(spu != nil, spu.BrandName, "")
			snapshotSupplier = k.If(spu != nil, spu.SupplierName, "")
			snapshotSpuType = k.If(spu != nil, spu.SpuType, 0)
		}
		if item.DishesID != 0 {
			snapshotName = k.If(dish != nil, dish.Name, "")
			snapshotProductImageURL = k.If(dish != nil, dish.Image, "")
			snapshotCategory = k.If(dish != nil, dish.CategoryName, "")
			snapshotCategoryID = k.If(dish != nil, dish.CategoryID, 0)
		}
		orderDetailList = append(orderDetailList, &model.OrdersDetailEntity{
			OrdersID:                ordersData.ID,           // 订单号
			SpuID:                   item.SpuID,              // 商品id,关联到spu表主键id
			DishesID:                item.DishesID,           // 菜品id,关联到dish表主键
			SpuCount:                spuCount,                // 商品数量
			SnapshotPrice:           price,                   // 快照单价
			SpuAmount:               spuCount.Mul(price),     // 商品金额小计
			SnapshotName:            snapshotName,            // 快照商品名称
			SnapshotProductImageURL: snapshotProductImageURL, // 快照产品图片
			SnapshotCategory:        snapshotCategory,        // 快照产品分类
			SnapshotCategoryID:      snapshotCategoryID,      // 快照产品分类ID
			SnapshotSpuType:         snapshotSpuType,         // 快照产品类型
			SnapshotUnit:            snapshotUnit,            // 快照产品单位
			SnapshotBrand:           snapshotBrand,           // 快照品牌
			SnapshotSupplier:        snapshotSupplier,        // 快照供应商
			Remark:                  item.Remark,             // 备注
		})
	}

	if err1 := tx.OrdersDetailEntity.WithContext(l.ctx).CreateInBatches(orderDetailList, len(orderDetailList)); err1 != nil {
		if err = tx.Rollback(); err != nil {
			return
		}
		return resp, errors.New("创建订单详情失败")
	}
	// 订单清单
	customerName, _ := service.EnterpriseCustomerService.GetNameByIdApi(l.ctx, accountInfo.CustomerId)
	if err1 := service.OrdersSpuService.CreateApi(l.ctx, tx, ordersData.ID, accountInfo.CustomerId, customerName, req.SendGoodsDate); err1 != nil {
		if err = tx.Rollback(); err != nil {
			return
		}
		return resp, errors.New("创建订单清单失败")
	}

	if err = tx.Commit(); err != nil {
		return resp, errors.New("创建失败")
	}
	return
}
